﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Specialized;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using log4net;
using SubSonic;
using ExtAspNet;



namespace TCMSystem
{
    public class PageBase : System.Web.UI.Page
    {
        #region static readonly

        private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        // Session key
        private static readonly string SK_ONLINE_UPDATE_TIME = "OnlineUpdateTime";
        //private static readonly string SK_USER_ROLE_ID = "UserRoleId";

        private static readonly string CHECK_POWER_FAIL_PAGE_MESSAGE = "您无权访问此页面！";
        private static readonly string CHECK_POWER_FAIL_ACTION_MESSAGE = "您无权进行此操作！";


        #endregion

        #region Module

        /// <summary>
        /// 本页面属于哪个模块
        /// </summary>
        public virtual ModuleType Module
        {
            get
            {
                return ModuleType.None;
            }
        }

        #endregion

        #region OnInit

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            if (!CheckPowerCanRead())
            {
                CheckPowerFailWithPage();
                return;
            }


            UpdateOnlineUser(User.Identity.Name);

            // 设置页面标题
            Page.Title = TblMstConfigHelper.Title;
        }

        #endregion

        #region GetQueryValue/GetQueryIntValue

        /// <summary>
        /// 获取查询字符串中的参数值
        /// </summary>
        protected string GetQueryValue(string queryKey)
        {
            return Request.QueryString[queryKey];
        }


        /// <summary>
        /// 获取查询字符串中的参数值
        /// </summary>
        protected int GetQueryIntValue(string queryKey)
        {
            int queryIntValue = -1;
            try
            {
                queryIntValue = Convert.ToInt32(Request.QueryString[queryKey]);
            }
            catch (Exception)
            {
                // TODO
            }

            return queryIntValue;
        }

        #endregion

        #region PageIndex/TotalCount/PageSize

        /// <summary>
        /// 当前显示第几页（从1开始）
        /// </summary>
        protected int PageIndex
        {
            get
            {
                if (ViewState["PageIndex"] == null)
                {
                    ViewState["PageIndex"] = 1;
                }
                return Convert.ToInt32(ViewState["PageIndex"]);
            }
            set
            {
                ViewState["PageIndex"] = value;
            }
        }
        /// <summary>
        /// 总共多少条记录
        /// </summary>
        protected int TotalCount
        {
            get
            {
                if (ViewState["TotalCount"] == null)
                {
                    ViewState["TotalCount"] = 0;
                }
                return Convert.ToInt32(ViewState["TotalCount"]);
            }
            set
            {
                ViewState["TotalCount"] = value;
            }
        }

        /// <summary>
        /// 每页显示多少条记录
        /// </summary>
        protected int PageSize
        {
            get
            {
                if (ViewState["PageSize"] == null)
                {
                    ViewState["PageSize"] = TblMstConfigHelper.PageSize;
                }
                return Convert.ToInt32(ViewState["PageSize"]);
            }
            set
            {
                ViewState["PageSize"] = value;
            }
        }

        /// <summary>
        /// 总共有多少页
        /// </summary>
        protected int PageCount
        {
            get
            {
                if (ViewState["PageCount"] == null)
                {
                    ViewState["PageCount"] = 1;
                }
                return Convert.ToInt32(ViewState["PageCount"]);
            }
            set
            {
                ViewState["PageCount"] = value;
            }
        }

        /// <summary>
        /// 排序字段
        /// </summary>
        protected string SortField
        {
            get
            {
                if (ViewState["SortField"] == null)
                {
                    ViewState["SortField"] = "addtime";
                }
                return ViewState["SortField"].ToString();
            }
            set
            {
                ViewState["SortField"] = value;
            }
        }

        /// <summary>
        /// 排序方向
        /// </summary>
        protected string SortDirection
        {
            get
            {
                if (ViewState["SortDirection"] == null)
                {
                    ViewState["SortDirection"] = "desc";
                }
                return ViewState["SortDirection"].ToString();
            }
            set
            {
                ViewState["SortDirection"] = value;
            }
        }


        #endregion

        #region GetSortExpression/GetTableColumnName

        /// <summary>
        /// 获取表格选中项DataKeys的第一个值，并转化为整型列表
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        protected List<int> GetSelectedDataKeyIDs(Grid grid)
        {
            List<int> ids = new List<int>();
            foreach (int rowIndex in grid.SelectedRowIndexArray)
            {
                ids.Add(Convert.ToInt32(grid.DataKeys[rowIndex][0]));
            }

            return ids;
        }

        /// <summary>
        /// 获取表格所有行DataKeys的第一个值，并转化为整型列表
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        protected List<int> GetDataKeyIDs(Grid grid)
        {
            List<int> ids = new List<int>();

            for (int i = 0; i < grid.Rows.Count; i++)
            {
                ids.Add(Convert.ToInt32(grid.DataKeys[i][0]));
            }

            return ids;
        }


        protected string GetSortExpression(Grid grid, TableSchema.Table schema)
        {
            GridColumn column = grid.Columns[grid.SortColumnIndex];
            string columnName = GetTableColumnName(schema, column.SortField);
            return String.Format("{0} {1}", columnName, grid.SortDirection);
        }

        protected string GetTableColumnName(TableSchema.Table table, string propertyName)
        {
            foreach (TableSchema.TableColumn column in table.Columns)
            {
                if (column.PropertyName == propertyName)
                {
                    return column.ColumnName;
                }
            }
            return String.Empty;
        }

        #endregion

        #region ResolveDeleteButtonForGrid/ResolveDDL

        /// <summary>
        /// 为删除Grid中选中项的按钮添加提示信息
        /// </summary>
        /// <param name="btn"></param>
        /// <param name="grid"></param>
        protected void ResolveDeleteButtonForGrid(ExtAspNet.Button btn, Grid grid)
        {
            ResolveDeleteButtonForGrid(btn, grid, "确定要删除选中的{0}项记录吗？");
        }

        protected void ResolveDeleteButtonForGrid(ExtAspNet.Button btn, Grid grid, string confirmTemplate)
        {
            ResolveDeleteButtonForGrid(btn, grid, "请至少应该选择一项记录！", confirmTemplate);
        }

        protected void ResolveDeleteButtonForGrid(ExtAspNet.Button btn, Grid grid, string noSelectionMessage, string confirmTemplate)
        {
            // 点击删除按钮时，至少选中一项
            btn.OnClientClick = grid.GetNoSelectionAlertInParentReference(noSelectionMessage);
            btn.ConfirmText = String.Format(confirmTemplate, "<span class=\"highlight\"><script>" + grid.GetSelectCountReference() + "</script></span>");
            btn.ConfirmTarget = Target.Top;
        }


        protected void ResolveDDL<T>(List<T> mys) where T : CustomTree, new()
        {

            ResolveDDL<T>(mys, -1, true);
        }

        protected void ResolveDDL<T>(List<T> mys, int currentId) where T : CustomTree, new()
        {
            ResolveDDL<T>(mys, currentId, true);
        }

        /// <summary>
        /// 将一个树型结构放在一个下列列表中可供选择
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="currentId"></param>
        /// <param name="mys"></param>
        protected void ResolveDDL<T>(List<T> mys, int currentId, bool addRootNode) where T : CustomTree, new()
        {
            if (addRootNode)
            {
                // 所有节点的TreeLevel加一，然后添加根节点
                foreach (T my in mys)
                {
                    my.TreeLevel += 1;
                }
                T root = new T();
                root.Title = "--根节点--";
                root.Id = 0;
                root.TreeLevel = 0;
                mys.Insert(0, root);
            }


            // currentId==-1表示当前节点不存在
            if (currentId != -1)
            {
                // 本节点不可点击（也就是说当前节点不可能是当前节点的父节点）
                // 并且本节点的所有子节点也不可点击，你想如果当前节点跑到子节点的子节点，那么这些子节点就从树上消失了
                bool startChileNode = false;
                int startTreeLevel = 0;
                foreach (T my in mys)
                {
                    if (my.Id == currentId)
                    {
                        startTreeLevel = my.TreeLevel;
                        my.Enabled = false;
                        startChileNode = true;
                    }
                    else
                    {
                        if (startChileNode)
                        {
                            if (my.TreeLevel > startTreeLevel)
                            {
                                my.Enabled = false;
                            }
                            else
                            {
                                startChileNode = false;
                            }
                        }
                    }
                }
            }
        }

        #endregion

        #region UpdateOnlineUser/LoginOnlineUser/GetOnlineCount

        protected void UpdateOnlineUser(string username)
        {
            DateTime now = DateTime.Now;
            object lastUpdateTime = Session[SK_ONLINE_UPDATE_TIME];
            if (lastUpdateTime == null || (Convert.ToDateTime(lastUpdateTime).Subtract(now).TotalMinutes > 5))
            {
                // 记录本次更新时间
                Session[SK_ONLINE_UPDATE_TIME] = now;

                TblMstOnline online = new Select().From<TblMstOnline>()
                      .Where(TblMstOnline.UserNameColumn).IsEqualTo(username)
                      .ExecuteSingle<TblMstOnline>();

                if (online != null)
                {
                    online.UpdateTime = now;
                    online.Save();
                }
            }
        }

        protected void LoginOnlineUser(TblMstUser user)
        {
            TblMstOnline online = new Select().From<TblMstOnline>()
                  .Where(TblMstOnline.UserIdColumn).IsEqualTo(user.Id)
                  .ExecuteSingle<TblMstOnline>();

            // 如果不存在，就创建一条新的记录
            if (online == null)
            {
                online = new TblMstOnline();
            }
            DateTime now = DateTime.Now;
            online.UserId = user.Id;
            online.UserName = user.Name;
            online.UserRealName = user.RealName;
            online.IPAdddress = Request.UserHostAddress;
            online.LoginTime = now;
            online.UpdateTime = now;
            online.Save();

            // 记录本次更新时间
            Session[SK_ONLINE_UPDATE_TIME] = now;

            //// 保存用户的角色ID（如果未定义，则为-1）
            //Session[SK_USER_ROLE_ID] = -1;
            //if (user.RoleId.HasValue)
            //{
            //    Session[SK_USER_ROLE_ID] = user.RoleId.Value;
            //}

        }

        protected int GetOnlineCount()
        {
            return new Select().From<TblMstOnline>()
                .Where(TblMstOnline.UpdateTimeColumn).IsGreaterThan(DateTime.Now.AddMinutes(-15))
                .GetRecordCount();
        }

        #endregion

        #region Module Power

        protected bool CheckPowerCanRead()
        {
            return CheckPower(ModulePowerType.CanRead);
        }

        protected bool CheckPowerNew()
        {
            return CheckPower(GetModulePowerType("New"));
        }

        protected bool CheckPowerEdit()
        {
            return CheckPower(GetModulePowerType("Edit"));
        }

        protected bool CheckPowerDelete()
        {
            return CheckPower(GetModulePowerType("Delete"));
        }

        protected string GetModuleImagePath()
        {
            return ModuleTypeHelper.Module2ImagePath(Module);
        }


        private ModulePowerType GetModulePowerType(string powerTypeName)
        {
            return ModulePowerTypeHelper.String2Power(String.Format("{0}_{1}", ModuleTypeHelper.Module2String(Module), powerTypeName));
        }


        // http://blog.163.com/zjlovety@126/blog/static/224186242010070024282/
        // http://www.cnblogs.com/gaoshuai/articles/1863231.html
        protected bool CheckPower(ModulePowerType powerType)
        {
            // 如果此页面不属于任何一个模块，则放行
            if (Module == ModuleType.None)
            {
                return true;
            }

            // 查询一个未定义的权限，则拒绝
            if (powerType == ModulePowerType.None)
            {
                return false;
            }

            // 如果此用户还未定义角色，则拒绝
            int roleId = GetIdentityRoleId();
            if (roleId <= 0)
            {
                return false;
            }

            Dictionary<string, RoleModulePower> roleModuleDic = RoleModulePowerHelper.GetRoleModulePowerDic(roleId);
            string moduleTypeName = ModuleTypeHelper.Module2String(Module);
            RoleModulePower modulePower = roleModuleDic[moduleTypeName];

            bool power = false;
            switch (powerType)
            {
                case ModulePowerType.CanRead:
                    power = modulePower.CanRead;
                    break;
                //case ModulePowerType.CanAdd:
                //    power = modulePower.CanAdd;
                //    break;
                //case ModulePowerType.CanEdit:
                //    power = modulePower.CanEdit;
                //    break;
                //case ModulePowerType.CanDelete:
                //    power = modulePower.CanDelete;
                //    break;
                default:
                    string powerTypeName = ModulePowerTypeHelper.GetPowerTypeName(powerType, moduleTypeName);
                    if (!String.IsNullOrEmpty(powerTypeName))
                    {
                        power = modulePower.OtherPowers.Value<bool?>(powerTypeName) ?? false;
                    }
                    break;
            }

            return power;
        }


        protected int GetIdentityRoleId()
        {
            FormsAuthenticationTicket ticket = ((FormsIdentity)User.Identity).Ticket;
            return Convert.ToInt32(ticket.UserData);
        }




        #endregion

        #region Power UI

        protected void CheckPowerFailWithPage()
        {
            Response.Write(CHECK_POWER_FAIL_PAGE_MESSAGE);
            Response.End();
        }

        protected void CheckPowerFailWithButton(ExtAspNet.Button btn)
        {
            btn.Enabled = false;
            btn.ToolTip = CHECK_POWER_FAIL_ACTION_MESSAGE;
        }

        protected void CheckPowerFailWithLinkButtonField(ExtAspNet.Grid grid, string columnId)
        {
            ExtAspNet.LinkButtonField btn = grid.FindColumn(columnId) as ExtAspNet.LinkButtonField;
            btn.Enabled = false;
            btn.ToolTip = CHECK_POWER_FAIL_ACTION_MESSAGE;
        }

        protected void CheckPowerFailWithWindowField(ExtAspNet.Grid grid, string columnId)
        {
            ExtAspNet.WindowField btn = grid.FindColumn(columnId) as ExtAspNet.WindowField;
            btn.Enabled = false;
            btn.ToolTip = CHECK_POWER_FAIL_ACTION_MESSAGE;
        }

        protected void CheckPowerFailWithAlert()
        {
            PageContext.RegisterStartupScript(Alert.GetShowInTopReference(CHECK_POWER_FAIL_ACTION_MESSAGE));
        }

        #region Power Button

        protected void CheckPowerWithButton(ModulePowerType powerType, ExtAspNet.Button btn)
        {
            if (!CheckPower(powerType))
            {
                CheckPowerFailWithButton(btn);
            }
        }

        protected void CheckPowerNewWithButton(ExtAspNet.Button btn)
        {
            if (!CheckPowerNew())
            {
                CheckPowerFailWithButton(btn);
            }
        }

        protected void CheckPowerEditWithButton(ExtAspNet.Button btn)
        {
            if (!CheckPowerEdit())
            {
                CheckPowerFailWithButton(btn);
            }
        }

        protected void CheckPowerDeleteWithButton(ExtAspNet.Button btn)
        {
            if (!CheckPowerDelete())
            {
                CheckPowerFailWithButton(btn);
            }
        } 

        #endregion

        #region Power Grid

        protected void CheckPowerDeleteWithLinkButtonField(ExtAspNet.Grid grid, string columnId)
        {
            if (!CheckPowerDelete())
            {
                CheckPowerFailWithLinkButtonField(grid, columnId);
            }
        }

        protected void CheckPowerEditWithLinkButtonField(ExtAspNet.Grid grid, string columnId)
        {
            if (!CheckPowerEdit())
            {
                CheckPowerFailWithLinkButtonField(grid, columnId);
            }
        }

        protected void CheckPowerWithLinkButtonField(ModulePowerType powerType, ExtAspNet.Grid grid, string columnId)
        {
            if (!CheckPower(powerType))
            {
                CheckPowerFailWithLinkButtonField(grid, columnId);
            }
        }


        protected void CheckPowerDeleteWithWindowField(ExtAspNet.Grid grid, string columnId)
        {
            if (!CheckPowerDelete())
            {
                CheckPowerFailWithWindowField(grid, columnId);
            }
        }

        protected void CheckPowerEditWithWindowField(ExtAspNet.Grid grid, string columnId)
        {
            if (!CheckPowerEdit())
            {
                CheckPowerFailWithWindowField(grid, columnId);
            }
        }

        protected void CheckPowerWithWindowField(ModulePowerType powerType, ExtAspNet.Grid grid, string columnId)
        {
            if (!CheckPower(powerType))
            {
                CheckPowerFailWithWindowField(grid, columnId);
            }
        } 
        #endregion

        #region Power Alert

        //protected void CheckPowerWithAlert(ModulePowerType powerType)
        //{
        //    if (!CheckPower(powerType))
        //    {
        //        CheckPowerFailWithAlert();
        //    }
        //}


        //protected void CheckPowerNewWithAlert()
        //{
        //    if (!CheckPowerNew())
        //    {
        //        CheckPowerFailWithAlert();
        //    }
        //}

        //protected void CheckPowerEditWithAlert()
        //{
        //    if (!CheckPowerEdit())
        //    {
        //        CheckPowerFailWithAlert();
        //    }
        //}

        //protected void CheckPowerDeleteWithAlert()
        //{
        //    if (!CheckPowerDelete())
        //    {
        //        CheckPowerFailWithAlert();
        //    }
        //} 

        #endregion

        #endregion

    }
}
